package org.ruoyi.ppt.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.ppt.domain.vo.PptStatusVo;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 *
 * @author anran
 * @date 2025/10/24 14:21
 */
@Slf4j
@Component
@ServerEndpoint("/ws/ppt")
public class PptWebSocketServer {
    // 保存连接会话
    private static final Map<String, Session> SESSION_MAP = new ConcurrentHashMap<>();


    /* 临时存放 Session ↔ pptId，用于 onClose 时清理 */
    private static final Map<Session, String> REVERSE_MAP = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session) {
        // 什么都不做，等待客户端第一条 JSON
        log.info("[WebSocket] 连接建立，等待客户端上报pptId");
    }

    @OnMessage   // 关键：第一次消息里带 {"pptId":"abc123"}
    public void onMessage(String json, Session session) {
        try {
            String pptId = JSONUtil.parseObj(json).getStr("pptId");
            if (StrUtil.isBlank(pptId)) {
                session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "pptId 为空"));
                return;
            }
            // 绑定
            SESSION_MAP.put(pptId, session);
            REVERSE_MAP.put(session, pptId);
            log.info("[WebSocket] 绑定成功 pptId={}", pptId);

            // 可选：立即推一条“已连接”
            sendMessage(pptId, new PptStatusVo(pptId, 1, 0, null, "已连接"));
        } catch (Exception e) {
            log.error("绑定失败", e);
            try { session.close(); } catch (IOException ignore) {}
        }
    }

    @OnClose
    public void onClose(Session session) {
        String pptId = REVERSE_MAP.remove(session);
        if (pptId != null) {
            SESSION_MAP.remove(pptId);
            log.info("[WebSocket] 连接关闭，pptId={}", pptId);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("[WebSocket] 发生错误", error);
    }

    public static void sendMessage(String pptId, PptStatusVo vo) {
        Session session = SESSION_MAP.get(pptId);
        if (session != null && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(JSONUtil.toJsonStr(vo));
                log.info("[WebSocket] 推送成功，pptId={}", pptId);
            } catch (Exception e) {
                log.error("[WebSocket] 推送失败，pptId={}", pptId, e);
            }
        }
    }
    /**
     * 推送最终态并立即断开连接
     */
    public static void sendMessageAndClose(String pptId, PptStatusVo vo) {
        Session session = SESSION_MAP.remove(pptId);   // 1. 先移除
        if (session != null && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(JSONUtil.toJsonStr(vo));
                log.info("[WebSocket] 推送成功，准备断开，pptId={}", pptId);
                session.close(new jakarta.websocket.CloseReason(
                        jakarta.websocket.CloseReason.CloseCodes.NORMAL_CLOSURE,
                        "推送完成，准备断开连接"));
            } catch (Exception e) {
                log.error("[WebSocket] 推送或关闭失败，pptId={}", pptId, e);
            }
        }
    }
}
